﻿//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Microsoft Public License.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace ODataDemo
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Data.Services;
    using System.Data.Services.Common;
    using System.Data.Services.Providers;
    using DataServiceProvider;

    public class ProductEntity
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public double Price { get; set; }
        public DateTime ReleaseDate { get; set; }
        public DateTime? DiscontinueDate { get; set; }
        public int Rating { get; set; }
        public CategoryEntity Category { get; set; }
    }

    public class CategoryEntity
    {
        public CategoryEntity()
        {
            this.Products = new List<ProductEntity>();
        }

        public int ID { get; set; }
        public string Name { get; set; }
        public List<ProductEntity> Products { get; set; }
    }

    public class DemoDSPDataService : DSPDataService<DSPContext>
    {
        protected override DSPContext CreateDataSource()
        {
            DSPContext context = System.Web.HttpContext.Current.Session["DSPContext"] as DSPContext;

            if (context == null)
            {
                context = new DSPContext();

                IList products = context.GetResourceSetEntities("Products");

                ProductEntity bread = new ProductEntity();
                bread.ID = 0;
                bread.Name = "Bread";
                bread.Description = "Whole wheat bread";
                bread.Price = 3.5; // This will never get to the client
                bread.ReleaseDate = new DateTime(1992, 1, 1);
                bread.DiscontinueDate = null;
                bread.Rating = 4;
                products.Add(bread);

                ProductEntity milk = new ProductEntity();
                milk.ID = 1;
                milk.Name = "Milk";
                milk.Description = "Low fat milk";
                milk.Price = 2.4; // This will never get to the client
                milk.ReleaseDate = new DateTime(1995, 10, 21);
                milk.DiscontinueDate = null;
                milk.Rating = 3;
                products.Add(milk);

                ProductEntity wine = new ProductEntity();
                wine.ID = 2;
                wine.Name = "Wine";
                wine.Description = "Red wine, year 2003";
                wine.Price = 19.9; // This will never get to the client
                wine.ReleaseDate = new DateTime(2003, 11, 24);
                wine.DiscontinueDate = new DateTime(2008, 3, 1);
                wine.Rating = 5;
                products.Add(wine);

                IList categories = context.GetResourceSetEntities("Categories");

                CategoryEntity food = new CategoryEntity();
                food.ID = 0;
                food.Name = "Food";
                categories.Add(food);

                CategoryEntity beverages = new CategoryEntity();
                beverages.ID = 1;
                beverages.Name = "Beverages";
                categories.Add(beverages);

                bread.Category = food;
                food.Products.Add(bread);
                milk.Category = beverages;
                beverages.Products.Add(milk);
                wine.Category = beverages;
                beverages.Products.Add(wine);
            }

            return context;
        }

        protected override DSPMetadata CreateDSPMetadata()
        {
            DSPMetadata metadata = new DSPMetadata("DemoService", "DataServiceProviderDemo");

            // Rename the type to "Product"
            ResourceType product = metadata.AddEntityType(typeof(ProductEntity), "Product");
            metadata.AddKeyProperty(product, "ID");
            metadata.AddPrimitiveProperty(product, "Name");
            metadata.AddPrimitiveProperty(product, "Description");
            // By not adding the Price property to metadata we're hiding it from the users of the service,
            //   there's no way users can even know that such property exists, let alone get its value.
            metadata.AddPrimitiveProperty(product, "ReleaseDate");
            metadata.AddPrimitiveProperty(product, "DiscontinueDate");
            metadata.AddPrimitiveProperty(product, "Rating");

            ResourceSet products = metadata.AddResourceSet("Products", product);

            ResourceType category = metadata.AddEntityType(typeof(CategoryEntity), "Category");
            metadata.AddKeyProperty(category, "ID");
            metadata.AddPrimitiveProperty(category, "Name");

            ResourceSet categories = metadata.AddResourceSet("Categories", category);

            // Add reference properties between category and product
            metadata.AddResourceReferenceProperty(product, "Category", categories);
            metadata.AddResourceSetReferenceProperty(category, "Products", products);

            return metadata;
        }

        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
            config.DataServiceBehavior.AcceptProjectionRequests = true;
        }
    }
}
